/*
XPTracker - Alternative Agile Tracking Tool
Copyright (C) 2006-2009  Stephen Starkey

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
*/
package org.xptracker.services.reports;

import com.google.inject.Injector;
import org.joda.time.DateTime;
import org.xptracker.domain.Size;
import org.xptracker.persistence.PersistenceManager;
import org.xptracker.test.IntegrationTest;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.SortedMap;

public class StoryHistoryTest extends IntegrationTest {
  private ReportFactory factory;


  protected Class[] getExtraDomainClasses() {
    return new Class[] {MockStoryState.class};
  }

  protected void afterInjection(Injector injector) {
    factory = new ReportFactory();
    injector.injectMembers(factory);
  }

  public void testStoryHistory() throws Exception {
    mgr.inTransaction(new PersistenceManager.UpdateHandler<Object>() {
      public Object doUpdate(PersistenceManager.UpdateReceiver receiver) {
        receiver.insert(new MockStoryState("42", date("2006-01-01"), 0, Size.medium));
        receiver.insert(new MockStoryState("42", date("2006-01-05"), 2, Size.medium));
        receiver.insert(new MockStoryState("42", date("2006-01-06"), 3, Size.medium));
        receiver.insert(new MockStoryState("42", date("2006-01-08"), 4, Size.large));
        receiver.insert(new MockStoryState("42", date("2006-01-08"), 6, Size.large));
        receiver.insert(new MockStoryState("42", date("2006-01-10"), 5, Size.large));
        return null;
      }
    });

    SortedMap<Date, Double> timeline = factory.makeStoryHistory(StoryHistory.ESTIMATES, "42").getTimeline();
    assertNotNull(timeline);

    assertEquals(5, timeline.size());
    assertEquals(0, timeline.get(date("2006-01-01")), 0.01);
    assertEquals(2, timeline.get(date("2006-01-05")), 0.01);
    assertEquals(3, timeline.get(date("2006-01-06")), 0.01);
    assertEquals(6, timeline.get(date("2006-01-08")), 0.01);
    assertEquals(5, timeline.get(date("2006-01-10")), 0.01);

    SortedMap<Date, Size> sizeTimeline = factory.makeStoryHistory(StoryHistory.SIZES, "42").getTimeline();
    assertNotNull(sizeTimeline);
    assertEquals(5, sizeTimeline.size());
    assertEquals(Size.medium, sizeTimeline.get(date("2006-01-01")));
    assertEquals(Size.medium, sizeTimeline.get(date("2006-01-05")));
    assertEquals(Size.medium, sizeTimeline.get(date("2006-01-06")));
    assertEquals(Size.large, sizeTimeline.get(date("2006-01-08")));
    assertEquals(Size.large, sizeTimeline.get(date("2006-01-10")));
  }

  public void testStoryHistoryWithRange() throws Exception {
    mgr.inTransaction(new PersistenceManager.UpdateHandler<Object>() {
      public Object doUpdate(PersistenceManager.UpdateReceiver receiver) {
        receiver.insert(new MockStoryState("42", date("2006-01-01"), 0, Size.medium));
        receiver.insert(new MockStoryState("42", date("2006-01-05"), 2, Size.medium));
        receiver.insert(new MockStoryState("42", date("2006-01-06"), 3, Size.medium));
        receiver.insert(new MockStoryState("42", date("2006-01-08"), 4, Size.large));
        receiver.insert(new MockStoryState("42", date("2006-01-08"), 6, Size.large));
        receiver.insert(new MockStoryState("42", date("2006-01-10"), 5, Size.large));
        return null;
      }
    });

    SortedMap<Date, Double> timeline = factory.makeStoryHistory(StoryHistory.ESTIMATES, "42").getTimeline(
        new DateTime("2006-01-07").toDate(), new DateTime("2006-01-10").toDate());
    assertNotNull(timeline);

    assertEquals(3, timeline.size());
    assertEquals(3, timeline.get(date("2006-01-07")), 0.01);
    assertEquals(6, timeline.get(date("2006-01-08")), 0.01);
    assertEquals(5, timeline.get(date("2006-01-10")), 0.01);

    SortedMap<Date, Size> sizeTimeline = factory.makeStoryHistory(StoryHistory.SIZES, "42").getTimeline(
        new DateTime("2006-01-07").toDate(), new DateTime("2006-01-10").toDate());
    assertNotNull(sizeTimeline);
    assertEquals(3, sizeTimeline.size());
    assertEquals(Size.medium, sizeTimeline.get(date("2006-01-07")));
    assertEquals(Size.large, sizeTimeline.get(date("2006-01-08")));
    assertEquals(Size.large, sizeTimeline.get(date("2006-01-10")));
  }

  public void testStoryHistoryOutOfRange() throws Exception {
    mgr.inTransaction(new PersistenceManager.UpdateHandler<Object>() {
      public Object doUpdate(PersistenceManager.UpdateReceiver receiver) {
        receiver.insert(new MockStoryState("42", date("2006-01-08"), 4, Size.large));
        receiver.insert(new MockStoryState("42", date("2006-01-08"), 6, Size.large));
        receiver.insert(new MockStoryState("42", date("2006-01-10"), 5, Size.large));
        return null;
      }
    });

    SortedMap<Date, Double> timeline = factory.makeStoryHistory(StoryHistory.ESTIMATES, "42").getTimeline(
        new DateTime("2006-01-07").toDate(), new DateTime("2006-01-10").toDate());
    assertNotNull(timeline);

    assertEquals(2, timeline.size());
    assertEquals(null, timeline.get(date("2006-01-07")));
    assertEquals(6, timeline.get(date("2006-01-08")), 0.01);
    assertEquals(5, timeline.get(date("2006-01-10")), 0.01);

    SortedMap<Date, Size> sizeTimeline = factory.makeStoryHistory(StoryHistory.SIZES, "42").getTimeline(new DateTime("2006-01-07").toDate(),
        new DateTime("2006-01-10").toDate());
    assertNotNull(sizeTimeline);
    assertEquals(2, sizeTimeline.size());
    assertEquals(null, sizeTimeline.get(date("2006-01-07")));
    assertEquals(Size.large, sizeTimeline.get(date("2006-01-08")));
    assertEquals(Size.large, sizeTimeline.get(date("2006-01-10")));
  }

  private Date date(String dateStr) {
    try {
      return new SimpleDateFormat("yyyy-MM-dd").parse(dateStr);
    } catch (ParseException e) {
      throw new RuntimeException(e);
    }
  }
}
